package com.bjpowernode.controller;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bjpowernode.domain.Order;
import com.bjpowernode.model.QueueConstant;
import com.bjpowernode.model.Result;
import com.bjpowernode.model.SpikeConstant;
import com.bjpowernode.service.OrderService;
import com.bjpowernode.utils.SensitiveWord;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@Api("订单管理接口")
public class OrderController {
    @Resource
    private BitMapBloomFilter bloomFilter;


    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private OrderService orderService;
    /**
     * 秒杀
     * 根据房屋id抢购房屋
     * 先过滤请求 每天单个请求数量只能在10个 如果超过10个则拦截掉
     * 一个用户只能抢购一次，需要使用布隆过滤器
     * 当抢购才可以放入mq 操作数据库
     *
     * @param id 订购商品的主键
     * @return
     */

    @PostMapping("buyaction")
    @ApiOperation("用户秒杀订单接口")
    public Result<String> buyAction(String id) {
        // 从上下文中拿到当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String jsonString = authentication.getPrincipal().toString();
        // 使用json拿到用户的id因为我们存的时候就是存的id,为什么要使用json转换呢,因为在存入上下的时候,Security又转换了一次
        JSONObject jsonObject = JSON.parseObject(jsonString);
        // 通过key拿到对应的value
        Integer userId = jsonObject.getInteger("username");
        // 先看布隆过滤器里面有没有 把用户id和房间id作为一个唯一标识
        boolean contains = bloomFilter.contains(userId + "-" + id);
        if (contains) {
            return Result.success("您已经抢过改房间，请稍后去我的订单查详情", null);
        }
        // 加入过滤器 防止改用户一直刷接口
        bloomFilter.add(userId + "-" + id);
        // 借助redis判断改房子的请求，统计请求
        Long increment = stringRedisTemplate.opsForValue().increment(SpikeConstant.HOUSE_REQUEST_PREFIX + id);
        if (increment > 3) {
            // 后面的直接拦截掉 这个房子已经有3个人抢了  房子只有一个
            return Result.success("手慢了，没有抢到房源，下次早点来哦",null);
        }
        Map<String, String> map = new HashMap<>(4);
        map.put("userId", userId.toString());
        map.put("houseId", id);
        // 当上面条件都满足了 就放入mq 异步消费消息，返回请求 让线程立即回收
        rabbitTemplate.convertAndSend(QueueConstant.SPIKE_EX, QueueConstant.SPIKE_KEY, JSON.toJSONString(map), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                String messageId = UUID.randomUUID().toString().replaceAll("-", "");
                message.getMessageProperties().setMessageId(messageId);
                return message;
            }
        });
        return Result.success("正在拼命抢购中，请稍后去我的订单查看是否成功",null);
    }

    @GetMapping("order")
    @ApiOperation("用户订单查询接口")
    public Result<List<Order>> getOrdersByUser(){
        // 从上下文中获取用户的信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        JSONObject jsonObject = JSON.parseObject(authentication.getPrincipal().toString());
        String userId = jsonObject.get("username").toString();
        List<Order> orderList = orderService.getOrdersByUser(userId);
        return Result.success("ok",orderList);
    }

    @PostMapping("feelback")
    public Result<String> feelback (Integer rate,String feelback,Integer orderId){
        // 进行脱敏处理
        SensitiveWord sw = new SensitiveWord("CensorWords.txt");
        sw.InitializationWork();
        String updateStr = sw.filterInfo(feelback);
        Boolean flag =  orderService.doFeelback(rate,updateStr,orderId);
        if (flag) {
            return Result.success("ok","评价成功");
        }
        return Result.success("500","评价失败");
    }
}
